package ru.nlezhnev.utils;

import java.util.Iterator;
import java.util.Map;

public class MapUtils {
//	@SuppressWarnings("unchecked")
	static public void destroy(Map currentMap, Map deleteMap) {
		Iterator<?> iter = deleteMap.keySet().iterator();
		while (iter.hasNext()) {
			String key = (String)iter.next();
			if (deleteMap.get(key) instanceof Map 
					&& currentMap.get(key) instanceof Map){
				destroy((Map)currentMap.get(key), (Map)deleteMap.get(key));
			} else {
				currentMap.remove(key);
			}
		}		
	}
	
	@SuppressWarnings("unchecked")
	static public void merge(Map base, Map target) {
		if (target == null) {
			return;
		}
		Iterator<?> iter = target.keySet().iterator();
		while (iter.hasNext()) {
			Object key = iter.next();
			Object sourceValue = getValue(base, key);
			Object targetValue = getValue(target, key);
			if (!containsKey(base, key) || isAtomicValue(targetValue) || isAtomicValue(sourceValue)) {
				base.put(key, targetValue); //replace
			} else if (sourceValue instanceof Map && targetValue instanceof Map) {
				merge((Map)sourceValue, (Map)targetValue);
			} else {
				System.out.println("Can't merge " + sourceValue + " and " + targetValue);
			}
		}
	}
	
	static public boolean containsKey(Map map, Object key) {
		if (map.containsKey(key)) {
			return true;
		}
		
		if (map.containsKey(key.toString())) {
			return true;
		}

		try {
			if (map.containsKey(Integer.parseInt(key.toString()))) {
				return true;
			}
		} catch (NumberFormatException e) {}
		
		return false;
	}
	
	static public Object getValue(Map map, Object key) {
		Object value = map.get(key);
		if (value == null) {
			value = map.get(key.toString());
		}
		if (value == null) {
			try {
				value = map.get(Integer.parseInt(key.toString()));
			} catch (NumberFormatException e) {
				value = null;
			}
		}
		return value;
	}
	
	static private boolean isAtomicValue(Object value) {
		return value == null
			|| value instanceof Boolean 
			|| value instanceof Integer 
			|| value instanceof String
			|| value instanceof Number
			|| value instanceof Object[];
	}
}
